package com.pubinfo.passbook.common.service.master.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pubinfo.passbook.common.entity.TRabbitmqOrgPersonMerge;
import com.pubinfo.passbook.common.entity.TRabbitmqPersonConvert;
import com.pubinfo.passbook.common.mapper.TRabbitmqOrgPersonMergeMapper;
import com.pubinfo.passbook.common.mapper.TRabbitmqPersonConvertMapper;
import com.pubinfo.passbook.common.model.bo.rabbitmq.RabbitMqRoot;
import com.pubinfo.passbook.common.model.bo.rabbitmq.TbAcctOrgRel;
import com.pubinfo.passbook.common.model.dto.system.OrgTreeColleagueListParam;
import com.pubinfo.passbook.common.model.dto.system.OrgTreePersonListParam;
import com.pubinfo.passbook.common.model.dto.system.PersonListParam;
import com.pubinfo.passbook.common.model.vo.persion.RabbitmqPersonConvertVO;
import com.pubinfo.passbook.common.service.dubbo.DubboService;
import com.pubinfo.passbook.common.service.master.TRabbitmqPersonConvertService;
import com.pubinfo.passbook.common.utils.StreamUtils;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author zhouch
 * @date 2021/10/27 15:10
 */
@Log4j2
@Service
public class TRabbitmqPersonConvertServiceImpl
    extends ServiceImpl<TRabbitmqPersonConvertMapper, TRabbitmqPersonConvert>
    implements TRabbitmqPersonConvertService {
    @Autowired
    DubboService dubboService;
    @Resource
    TRabbitmqOrgPersonMergeMapper orgPersonMergeMapper;
    
    @Override
    public Boolean processPersonMsg(RabbitMqRoot personMsg) {
        
        String handleType = personMsg.getHandle();
        
        TRabbitmqPersonConvert person = new TRabbitmqPersonConvert(personMsg.getContext());

        boolean hasExist = new LambdaQueryChainWrapper<>(baseMapper)
                .eq(TRabbitmqPersonConvert::getAcctId, person.getAcctId())
                .count() > 0;

        switch (handleType) {
            case "insert":
            case "update":

                // 插入或者更新
                return saveOrUpdateWithOrgRef(person);

            case "delete":

                return new LambdaUpdateChainWrapper<>(baseMapper)
                        .eq(TRabbitmqPersonConvert::getAcctId, person.getAcctId())
                        .remove();

            default:
                return false;
        }
    }
    
    @Override
    public IPage<RabbitmqPersonConvertVO> searchPersonsByKeyword(PersonListParam params) {
    
        return baseMapper.getPersonsListByKeyword(
            params.getPage(),
            params
        );
    }

    /**
     * 保存或者更新, 同时更新账户组织关系
     *
     * @param person
     * @return
     */
    @Override
    public boolean saveOrUpdateWithOrgRef(TRabbitmqPersonConvert person) {
        log.info("新增人员 {}", person.toString());
        return saveOrUpdate(person) && refreshRefOrgIdFromPerson(person);
    }

    /**
     * 保存或者更新, 同时更新账户组织关系
     *
     * @param person
     * @return
     */
    @Override
    public boolean batchSaveOrUpdateWithOrgRef(Collection<TRabbitmqPersonConvert> person) {
        log.info("批量新增人员 {}", person.stream()
                .map(TRabbitmqPersonConvert::getAcctId).collect(Collectors.toList()).toString());

        if (saveOrUpdateBatch(person)) {
            for (TRabbitmqPersonConvert p : person) {
                refreshRefOrgIdFromPerson(p);
            }
            return true;
        } else {
            return false;
        }
    }

    @Override
    public IPage<TRabbitmqPersonConvert> getPersonsByOrgId(OrgTreePersonListParam params) {
        return orgPersonMergeMapper.getPersonsListByOrgRefs(
                params.getPage("create_time"),
                params.getOrgId(),
                params.getRealname());
    }

    @Override
    public IPage<TRabbitmqPersonConvert> getPersonsByPersonOrgId(OrgTreeColleagueListParam params) {
      Set<Long> orgIds = new HashSet<>();
  
      if (params.getOrgId() != null) {
        orgIds.add(params.getOrgId());
      } else {
        // 先获得该用户所有的组织关系
        List<TRabbitmqOrgPersonMerge> opms = new LambdaQueryChainWrapper<>(orgPersonMergeMapper)
            .eq(TRabbitmqOrgPersonMerge::getAcctId, String.valueOf(params.getAcctId()))
            .list();

            // 取出所有组织ID
            orgIds = opms.stream().map(t -> t.getOrgId()).collect(Collectors.toSet());
        }

        return orgPersonMergeMapper.getPersonsListByOrgsRefs(
                params.getPage("create_time"),
                orgIds,
                null
        );
    }

    @Override
    public List<TRabbitmqPersonConvert> getPersonsByPersonOrgId(String acct) {
        Set<Long> orgIds = new HashSet<>();
        // 先获得该用户所有的组织关系
        List<TRabbitmqOrgPersonMerge> opms = new LambdaQueryChainWrapper<>(orgPersonMergeMapper)
                .eq(TRabbitmqOrgPersonMerge::getAcctId, String.valueOf(acct))
                .list();
        // 取出所有组织ID
        orgIds = opms.stream().map(t -> t.getOrgId()).collect(Collectors.toSet());
        return orgPersonMergeMapper.getPersonsListByOrgsRefs(
                orgIds,
                null
        );
    }

    @Override
    public Boolean hasColleague(Integer acctId, Integer acctId2) {
        Set<Long> acctIdorgIds = new HashSet<>();
        // 先获得acct用户Id所有的组织关系
        List<TRabbitmqOrgPersonMerge> opms = new LambdaQueryChainWrapper<>(orgPersonMergeMapper)
                .eq(TRabbitmqOrgPersonMerge::getAcctId, String.valueOf(acctId))
                .list();
        // 取出所有组织ID
        acctIdorgIds = opms.stream().map(t -> t.getOrgId()).collect(Collectors.toSet());

        Set<Long> acctId2orgIds = new HashSet<>();

        // 先获得acct2用户Id所有的组织关系
        List<TRabbitmqOrgPersonMerge> opms2 = new LambdaQueryChainWrapper<>(orgPersonMergeMapper)
                .eq(TRabbitmqOrgPersonMerge::getAcctId, String.valueOf(acctId2))
                .list();
        // 取出所有组织ID
        acctId2orgIds = opms2.stream().map(t -> t.getOrgId()).collect(Collectors.toSet());

        Boolean isColleague = false;

        for (Long acctOrgId : acctIdorgIds) {
            for (Long acct2OrgId : acctId2orgIds) {
                if (acct2OrgId.equals(acctOrgId)) {
                    isColleague = true;
                }
            }
        }

        return isColleague;
    }


    @Override
    public TRabbitmqPersonConvert getPersonByAcct(String ncCode) {
        return baseMapper.getPersonByAcct(ncCode);
    }

    /**
     * 刷新账户与的组织的关联
     *
     * @return
     */
    private boolean refreshRefOrgIdFromPerson(TRabbitmqPersonConvert person) {
        List<TbAcctOrgRel> orgRels = person.getTbAcctOrgRel();

        // 去掉重复的组织ID
        List<TbAcctOrgRel> realOrgRels = orgRels.stream()
                .filter(StreamUtils.distinctByKey(t -> t.getOrgId())).collect(Collectors.toList());

        log.info("重新映射人员组织关系 {}", realOrgRels.toString());

        // 删除所有原有的关联
        new LambdaUpdateChainWrapper<>(orgPersonMergeMapper)
                .eq(TRabbitmqOrgPersonMerge::getAcctId, person.getAcctId())
                .remove();

        // 将新消息中的所有关联包装成TRabbitmqOrgPersonMerge
        List<TRabbitmqOrgPersonMerge> merges = orgRels.stream().map(t -> {
                    TRabbitmqOrgPersonMerge merge = new TRabbitmqOrgPersonMerge();
                    merge.setAcctId(String.valueOf(person.getAcctId()));
                    merge.setOrgId(Long.valueOf(t.getOrgId()));
                    return merge;
                })
                .collect(Collectors.toList());

        if (merges.isEmpty() == false) {
            orgPersonMergeMapper.insertBatch(merges);
        }

        return true;
    }
}
